﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using IndieStudio.BugsBang.Utility;

///Developed By Indie Studio
///https://assetstore.unity.com/publishers/9268
///www.indiestd.com
///info@indiestd.com

namespace IndieStudio.BugsBang.Game
{
    [DisallowMultipleComponent]
    [RequireComponent(typeof(PathObjectMove))]
    public class PathObject : MonoBehaviour
    {
        /// <summary>
        /// The type of the object.
        /// </summary>
        public Type type;

        /// <summary>
        /// Whether this object is a target or not.
        /// </summary>
        public bool isTarget;

        /// <summary>
        /// The index of the target.
        /// Mainly used to determine the UI reference of the target
        /// </summary>
        [HideInInspector]
        public int targetIndex = -1;

        /// <summary>
        /// The animator comp.
        /// </summary>
        private Animator animatorComp;

        /// <summary>
        /// The path object move component.
        /// </summary>
        [HideInInspector]
        public PathObjectMove pathObjectMove;

        /// <summary>
        /// Whether the object is in the destroying process or not.
        /// </summary>
        private bool isDestroying;

        void Awake()
        {
            //Set up references

            animatorComp = GetComponent<Animator>();
            pathObjectMove = GetComponent<PathObjectMove>();
        }

        // Use this for initialization
        void Start()
        {

        }

        // Update is called once per frame
        void Update()
        {

        }

        /// <summary>
        /// On destroy this instance event.
        /// </summary>
        void OnDestroy()
        {
            if (Paths.instance != null)
            {
                //Remove this item from the Paths pool
                Paths.instance.DeleteByIntanceID(GetInstanceID());
            }
        }

        /// <summary>
        /// Create the trail effect for the path object.
        /// </summary>
        /// <param name="effect">Effect GameObject.</param>
        public void CreateTrailEffect(GameObject effect)
        {
            if (type == Type.FLY && effect != null)
            {
                Instantiate(effect, transform);
            }
        }

        /// <summary>
        /// Set the speed of the animator.
        /// </summary>
        /// <param name="speed">Speed of animator.</param>
        public void SetAnimatorSpeed(float speed)
        {
            if (animatorComp != null)
            {
                animatorComp.speed = speed;
            }
        }

        /// <summary>
        /// Move the path object.
        /// </summary>
        public void Move()
        {
            if (isDestroying)
                return;

            pathObjectMove.Move();
        }

        /// <summary>
        /// Stop the path object.
        /// </summary>
        public void Stop()
        {
            pathObjectMove.Stop();
        }

        /// <summary>
        ///  On collider trigger enter event.
        /// </summary>
        /// <param name="other">Other collider2D.</param>
        void OnTriggerEnter2D(Collider2D other)
        {
            /*
			 //Reverse direction on collision with another object
			PathObject otherPathObject = other.GetComponent<PathObject> ();
			//If collision triggered with creeper
			if (type == Type.CREEPER && otherPathObject!=null) {
				if (otherPathObject.type == Type.CREEPER) {
					otherPathObject.GetComponent<PathObjectMove> ().Reverse ();
				}
			}*/
        }

        /// <summary>
        /// Release/Remove the resources of this instance.
        /// </summary>
        public void ReleaseResources()
        {
            Destroy(animatorComp);
            Destroy(GetComponent<BoxCollider2D>());
            Destroy(GetComponent<Rigidbody2D>());
            Destroy(this);
            Destroy(GetComponent<PathObjectMove>());
        }

        /// <summary>
        /// On user hit event.
        /// </summary>
        /// <param name="destroyMode">Destroy mode.</param>
        /// <param name="destroyEffects">Destroy effects.</param>
        /// <param name="playDestroySFX">If set to <c>true</c> then play the destroy SFX.</param>
        public void OnHit(DestroyMode destroyMode, GameObject[] destroyEffects, bool playDestroySFX)
        {
            isDestroying = true;

            if (isTarget && targetIndex != -1)
            {

                //Increase the UI score of target
                if (!GameManager.instance.targetsScore[targetIndex].IsFull())
                {
                    GameManager.instance.targetsScore[targetIndex].cover.fillAmount -= 1.0f / LevelsManager.instance.GetCurrentLevel().targets[targetIndex].count;
                    GameManager.instance.targetsScore[targetIndex].IncrementValue();
                }

                //Increase level score by 10 ,when user hit a target
                Instantiate(GameManager.instance.scoreBonusEffect, transform.position, Quaternion.identity);
                GameManager.instance.levelScore += 10;
                GameManager.instance.SetScoreText(GameManager.instance.levelScore);
            }
            else
            {

                //Vibrate on hit wrong object
                GameManager.Vibrate();

                //Decrease level score by 5 , when user hit a wrong object
                Instantiate(GameManager.instance.scorePenaltyEffect, transform.position, Quaternion.identity);
                GameManager.instance.levelScore -= 5;

                //Clamp level score as min value equals 0
                if (GameManager.instance.levelScore < 0)
                {
                    GameManager.instance.levelScore = 0;
                }

                //Set Score Text value
                GameManager.instance.SetScoreText(GameManager.instance.levelScore);

                //Decrease the lives
                GameManager.instance.currentLives--;
                //Set lives fill value
                GameManager.instance.SetLivesFillValue(GameManager.instance.currentLives);

                //On current lives equals zero
                if (GameManager.instance.currentLives == 0)
                {
                    GameManager.instance.OnLivesEqualsZero();
                }
            }

            //Disable the collider
            GetComponent<Collider2D>().enabled = false;

            if (animatorComp != null)
                animatorComp.enabled = false;

            int effectIndex = -1;
            if (destroyMode == DestroyMode.RANDOM)
            {
                effectIndex = Random.Range(0, 2);
                destroyMode = effectIndex == 1 ? DestroyMode.RAY : DestroyMode.SMASH;
            }

            Vector3 tempVector;
            float smashDestroyTime = 2;
            if (destroyMode == DestroyMode.RAY)
            {
                //Ray Destory
                effectIndex = 0;
                Destroy(gameObject);
            }
            else if (destroyMode == DestroyMode.SMASH)
            {
                //Smash Destroy
                effectIndex = 1;
                tempVector = transform.localScale;
                tempVector.x *= 1.2f;
                tempVector.y *= 1f;
                transform.localScale = tempVector;
                Stop();
                Destroy(gameObject, smashDestroyTime);
            }

            //Create destroy effect
            if (destroyEffects != null)
                if (effectIndex >= 0 && effectIndex < destroyEffects.Length)
                {
                    if (destroyEffects[effectIndex] != null)
                    {
                        tempVector = transform.position;
                        tempVector.z = 0;
                        GameObject effect = Instantiate(destroyEffects[effectIndex], tempVector, Quaternion.identity) as GameObject;

                        if (destroyMode == DestroyMode.SMASH)
                        {

                            //Set bug explosion parent to null , and destroy the effect after 3 seconds
                            Transform bugExplosion = effect.transform.Find("BugExplosion");
                            bugExplosion.SetParent(null);
                            bugExplosion.transform.position = transform.position;
                            Destroy(bugExplosion.gameObject, 3);

                            //Set start delay for explosion effect, and play explode sfx
                            var mainBugExplosion = bugExplosion.GetComponent<ParticleSystem>().main;
                            mainBugExplosion.startDelay = smashDestroyTime - 0.1f;

                            AudioSources.instance.Invoke("PlayObjectExplodeSFX", smashDestroyTime - 0.1f);

                            //Scale the Smash Effect based on its parent
                            effect.transform.SetParent(transform);

                            tempVector = transform.localScale;
                            tempVector.x = tempVector.y = transform.localScale.y * 1.35f;
                            effect.transform.localScale = tempVector;

                            RectTransform rectTransform = effect.GetComponent<RectTransform>();
                            rectTransform.offsetMax = rectTransform.offsetMin = Vector3.zero;
                            rectTransform.SetSiblingIndex(0);
                        }
                    }
                }

            //Play the destroy sound effect
            if (playDestroySFX)
                AudioSources.instance.PlayDestroySFX();

            //Check if the level is completed or not
            GameManager.instance.CheckLevelComplete();
        }

        /// <summary>
        /// Destroy this instance.
        /// </summary>
        public void DestroyInstance()
        {
            isDestroying = true;
            Destroy(gameObject);
        }

        /// <summary>
        /// Whether this instance is destroying or not.
        /// </summary>
        /// <returns><c>true</c> if this instance is destroying; otherwise, <c>false</c>.</returns>
        public bool IsDestroying()
        {
            return this.isDestroying;
        }

        public enum DestroyMode
        {
            RAY,
            SMASH,
            RANDOM,
            NONE
        }

        public enum Type
        {
            FLY,
            GROUND
        }
    }
}